package com.alfred.mall.order.biz.service;

import com.alfred.common.framwork.constant.DeletedStatusEnum;
import com.alfred.common.framwork.util.ServiceExceptionUtil;
import com.alfred.common.framwork.vo.CommonResult;
import com.alfred.mall.order.api.OrderService;
import com.alfred.mall.order.api.bo.*;
import com.alfred.mall.order.api.constant.OrderErrorCodeEnum;
import com.alfred.mall.order.api.dto.CalcOrderPriceDTO;
import com.alfred.mall.order.api.dto.OrderCreateDTO;
import com.alfred.mall.order.api.dto.OrderQueryDTO;
import com.alfred.mall.order.biz.convert.OrderConvert;
import com.alfred.mall.order.biz.convert.OrderItemConvert;
import com.alfred.mall.order.biz.convert.OrderRecipientConvert;
import com.alfred.mall.order.biz.dao.OrderItemMapper;
import com.alfred.mall.order.biz.dao.OrderMapper;
import com.alfred.mall.order.biz.dao.OrderRecipientMapper;
import com.alfred.mall.order.biz.dataobject.OrderDO;
import com.alfred.mall.order.biz.dataobject.OrderItemDO;
import com.alfred.mall.order.biz.dataobject.OrderRecipientDO;
import com.alfred.mall.product.api.ProductSpuService;
import com.alfred.mall.product.api.bo.ProductSkuDetailBO;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单 orderService impl
 */
@Service
@org.apache.dubbo.config.annotation.Service(validation = "true", version = "${dubbo.provider.OrderService.version}")
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderRecipientMapper orderRecipientMapper;
    @Autowired
    private OrderItemMapper orderItemMapper;

    @Reference(validation = "true", version = "${dubbo.consumer.ProductSpuService.version}")
    ProductSpuService productSpuService;

    @Autowired
    private CardServiceImpl cardService;

    @Override
    public CommonResult<OrderPageBO> getOrderPage(OrderQueryDTO orderQueryDTO) {
        log.info("orderServiceImpl getOrderPage [{}]", orderQueryDTO);
        int totalCount = orderMapper.selectPageCount(orderQueryDTO);
        if (totalCount == 0) {
            //没有订单信息
            return CommonResult.success(new OrderPageBO().setOrders(Collections.emptyList()).setTotal(totalCount));
        }
        //获取订单信息
        List<OrderDO> orderDOList = orderMapper.selectPage(orderQueryDTO);
        if (CollectionUtils.isEmpty(orderDOList)) {
            return CommonResult.success(new OrderPageBO().setOrders(Collections.emptyList()).setTotal(totalCount));
        }
        //获取订单id
        Set<Integer> orderIds = orderDOList.stream().map(OrderDO::getId).collect(Collectors.toSet());
        //获取配送信息
        List<OrderRecipientDO> orderRecipientDOList = orderRecipientMapper.selectByOrderIds(orderIds);
        List<OrderRecipientBO> orderRecipientBOList = OrderRecipientConvert.INSTANCE.convert(orderRecipientDOList);
        Map<Integer, OrderRecipientBO> orderRecipientBOMap
                = orderRecipientBOList.stream().collect(Collectors.toMap(OrderRecipientBO::getOrderId, object -> object));
        //获取 订单的 items
        List<OrderItemDO> orderItemDOList = orderItemMapper
                .selectByDeletedAndOrderIds(orderIds, DeletedStatusEnum.DELETED_NO.getValue());
        List<OrderItemBO> orderItemBOList = OrderItemConvert.INSTANCE.convertOrderItemDO(orderItemDOList);
        Map<Integer, List<OrderItemBO>> orderItemBOMultiMap = orderItemBOList.stream().collect(
                Collectors.toMap(
                        OrderItemBO::getOrderId,
                        item -> Lists.newArrayList(item),
                        (oldValue, newValue) -> {
                            oldValue.addAll(newValue);
                            return oldValue;
                        }
                )
        );
        List<OrderBO> orderPageBOList = OrderConvert.INSTANCE.convertPageBO(orderDOList);
        List<OrderBO> result = orderPageBOList.stream().map(orderBO -> {
            if (orderItemBOMultiMap.containsKey(orderBO.getId())) {
                orderBO.setOrderItems(orderItemBOMultiMap.get(orderBO.getId()));
            }
            if (orderRecipientBOMap.containsKey(orderBO.getId())) {
                orderBO.setOrderRecipient(orderRecipientBOMap.get(orderBO.getId()));
            }
            return orderBO;
        }).collect(Collectors.toList());
        return CommonResult.success(
                new OrderPageBO()
                        .setTotal(totalCount)
                        .setOrders(result)
        );
    }

    @Override
    public CommonResult<OrderCreateBO> createOrder(OrderCreateDTO orderCreateDTO) {
        Integer userId = orderCreateDTO.getUserId();
        List<OrderCreateDTO.OrderItem> orderItemDTOList = orderCreateDTO.getOrderItems();
        List<OrderItemDO> orderItemDOList = OrderItemConvert.INSTANCE.convert(orderItemDTOList);

        //获取商品信息
        Set<Integer> skuIds = orderItemDOList.stream().map(OrderItemDO::getSkuId).collect(Collectors.toSet());
        List<ProductSkuDetailBO> productList = productSpuService.getProductSkuDetailList(skuIds);
        if (orderItemDTOList.size() != productList.size()) {// 校验获得的数量，是否匹配
            return ServiceExceptionUtil.error(OrderErrorCodeEnum.ORDER_GET_GOODS_INFO_INCORRECT.getCode());
        }
        //价格计算


        return null;
    }


    private CalcOrderPriceBO calcOrderPrice(List<ProductSkuDetailBO> skus, OrderCreateDTO orderCreateDTO) {
        //创建计算的 DTO
        CalcOrderPriceDTO calcOrderPriceDTO = new CalcOrderPriceDTO()
                .setUserId(orderCreateDTO.getUserId())
                .setItems(new ArrayList<>(skus.size()))
                .setCouponCardId(orderCreateDTO.getCouponCardId());
        for(OrderCreateDTO.OrderItem item : orderCreateDTO.getOrderItems()){
            calcOrderPriceDTO.getItems().add(new CalcOrderPriceDTO.Item(item.getSkuId(),item.getQuantity(),true));
        }
        return cardService.calcOrderPrice(calcOrderPriceDTO);
    }
}
